#include "ftshowtext.h"

#define FTST_HOW_OVERLAP 20
#define FTST_BAR_SIZE 10
#define FTST_PADDING 4
#define FTST_TEXT_PADDING 5

FTShowText::FTShowText(const QString& t, QWidget *parent) :
    QWidget(parent)
{
    scroll_pos = total_text_height = scroll_bar_height = 0;
    setSizePolicy( QSizePolicy::Ignored, QSizePolicy::Ignored );
    parseText(t);
    font = QFont( "serif", 6 );
}

void FTShowText::setCurrentFont(const QFont & f )
{
    font = f;
}

void FTShowText::paintEvent(QPaintEvent * pe )
{
    int start_y = -scroll_pos;
    // The real visible creen area goes from scroll_pos to screen_h + scroll_pos
    int screen_h = height();
    QPainter painter(this);
    QRect base_rect = rect().adjusted( FTST_PADDING, FTST_PADDING,
                                       -FTST_PADDING, -FTST_PADDING );

    painter.setFont( font );


    int i = 0;
    int n_texts = text.count();
    int flags;
    QRectF text_rect;
    total_text_height = 0;

    for (i = 0; i < n_texts; i++ )
    {
        text_item ti = text.at(i);

        flags = Qt::AlignTop | Qt::TextWordWrap | ti.align;
        font.setBold( ti.style == bold );
        font.setItalic( ti.style == italic );
        painter.setFont( font );
        text_rect = painter.boundingRect( base_rect,
                                          flags,
                                          ti.text).translated( 0, start_y );
        ti.height = text_rect.height() + FTST_TEXT_PADDING;

        // Paint only strings that are below the top of the real visible screen area
        if ( ((start_y + ti.height) > 0) && (start_y < screen_h ) )
        {
            painter.drawText( text_rect,
                              flags,
                              ti.text );
        }
        start_y += ti.height;
        total_text_height += ti.height;
    }
    scroll_bar_height = (total_text_height-FTST_HOW_OVERLAP)<<1;

    // Draw the border to the widget
    painter.drawRect( rect().adjusted( 0,0,-1,-1) );

    if ( hasMouseTracking() )
    {
        painter.setBrush( QBrush( Qt::Dense4Pattern ) );
        painter.drawRect( width()-FTST_BAR_SIZE-3,
                          FTST_BAR_SIZE +
                          ((scroll_bar_height>>1)-scroll_pos)*(height()-FTST_BAR_SIZE*3)/scroll_bar_height,
                          FTST_BAR_SIZE,
                          FTST_BAR_SIZE);
    }
}


void FTShowText::mousePressEvent(QMouseEvent * me )
{
    setMouseTracking(true);
    mouse_start = me->globalY();
}

void FTShowText::mouseReleaseEvent(QMouseEvent * me)
{
    setMouseTracking(false);
}

void FTShowText::mouseMoveEvent(QMouseEvent * me)
{
    int overlap = total_text_height - FTST_HOW_OVERLAP;

    scroll_pos += mouse_start - me->globalY();
    mouse_start = me->globalY();

    if ( scroll_pos > overlap )
        scroll_pos = overlap;
    if ( scroll_pos < -overlap )
        scroll_pos = -overlap;

    update();
}

void FTShowText::parseText(const QString& t)
{
    QFontMetrics fm = fontMetrics();
    QRegExp rx("<\\s*([^>]+)\\s*>(.+)<\\/\\s*([^>]+)\\s*>");
    rx.setMinimal(true);
    int pos = 0;
    text.clear();
    total_text_height = 0;
    while ((pos = rx.indexIn(t, pos)) != -1)
    {
        QRegExp mx("(\\w+)\\|?([b|i]?)");
        mx.indexIn( rx.cap(1) );
        QString open = mx.cap(1);
        QString mod = mx.cap(2);
        QString value = rx.cap(2);
        QString close = rx.cap(3);
        if ( open == close )
        {
            text_item ti;
            if ( open == "center" )
                ti.align = Qt::AlignHCenter;
            else if ( open == "left" )
                ti.align = Qt::AlignLeft;
            else if ( open == "right" )
                ti.align = Qt::AlignRight;
            else if ( open == "justify" )
                ti.align = Qt::AlignJustify;
            if ( mod == "b" )
                ti.style = bold;
            else if ( mod == "i" )
                ti.style = italic;
            else
                ti.style = none;
            ti.text = value;
            ti.height = 0;
            text.append( ti );
        }
        pos += rx.matchedLength();
    }
    if ( text.count() == 0 )
    {
        text_item ti;
        ti.text = t.mid( pos );
        ti.align = Qt::AlignLeft;
        ti.style = none;
        ti.height = 0;
        text.append( ti );
    }
}
